package com.shiliuzi.www.util.excelUtil;

import com.alibaba.excel.EasyExcel;
import com.shiliuzi.www.common.Code;
import com.shiliuzi.www.exception.GlobalException;
import com.shiliuzi.www.mapper.DownloadMapper;
import com.shiliuzi.www.pojo.bo.util.DownloadExcelWriteBo;
import com.shiliuzi.www.pojo.po.RecordDefault;
import com.shiliuzi.www.pojo.po.RecordType;
import com.shiliuzi.www.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Excel表格导出
 */
@Slf4j
@Service
public class ExcelWriteUtil {

    @Resource
    private DownloadMapper downloadMapper;

    @Resource
    private CommonUtil commonUtil;

    private static CopyOnWriteArrayList<DownloadExcelWriteBo> targetExcel = new CopyOnWriteArrayList<>();

    /**
     * 核心导出方法
     * @param url
     * @param type
     * @return
     */
    public boolean excelWrite(String url, Integer type, String pathFile) {

        //当前用户桌面路径
        File desktopDir = FileSystemView.getFileSystemView() .getHomeDirectory();
        String desktopPath = desktopDir.getAbsolutePath();

        if (url==null) url = desktopPath;

        String fileName = url + "\\" + "member.xlsx";
        int suffer = 0;
        while (Files.exists(Paths.get(fileName))) {
            suffer++;
            int i = fileName.lastIndexOf(".");
            fileName = fileName.substring(0,i)+suffer+fileName.substring(i);
        }

        Integer infoNum = downloadMapper.excelInfoPage(type);

        if (infoNum == 0) return false;

        Integer readLimit = 0;
        Integer threadNum = 0;
        if (infoNum/100 == 0) {
            readLimit = 2;
            threadNum = 50;
        } else {
            readLimit = infoNum/100 + 1;
            threadNum = 100;
        }

        syncWriteObject(type,threadNum,readLimit,pathFile);

        while (targetExcel.size()!=infoNum) {
            continue;
        }

        EasyExcel.write(fileName, DownloadExcelWriteBo.class).sheet().doWrite(targetExcel);
        targetExcel.clear();
        return true;
    }

    /**
     * 导出excel的对象转换器
     * @param recordDefault
     * @return
     */
    private DownloadExcelWriteBo copyProperties(RecordDefault recordDefault) {
        try {
            DownloadExcelWriteBo downloadExcelWriteBo = new DownloadExcelWriteBo();

            Class clazzTarget = downloadExcelWriteBo.getClass();
            Class clazzSource = recordDefault.getClass();

            Field[] fields = clazzSource.getDeclaredFields();

            for (Field field : fields) {
                String fieldName = field.getName();
                String suffix = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);

                Method sourceMethod = clazzSource.getMethod("get" + suffix);

                if (fieldName.equals("classId")) {
                    Integer classId =(Integer) sourceMethod.invoke(recordDefault);

                    if (classId.equals(-1) || classId.equals(0)) {
                        downloadExcelWriteBo.setType("未填写");
                        downloadExcelWriteBo.setTypeContent("未填写");
                        continue;
                    }

                    RecordType recordType = downloadMapper.excelCheckType(classId);
                    if (recordType.getType().equals(0)) downloadExcelWriteBo.setType("惩罚");
                    else downloadExcelWriteBo.setType("奖励");
                    downloadExcelWriteBo.setTypeContent(recordType.getContent());
                    continue;
                }

                Method targetMethod = clazzTarget.getMethod("set" + suffix, field.getType());
                targetMethod.invoke(downloadExcelWriteBo,sourceMethod.invoke(recordDefault));
            }

            return downloadExcelWriteBo;
        } catch (Exception e) {
            throw new GlobalException(Code.SYS_ERR,"系统内部出错！导出excel的对象转换器宕机！");
        }
    }

    /**
     * 异步读取数据
     * @param type
     * @param threadNum
     * @param readLimit
     */
    private void syncWriteObject(Integer type ,Integer threadNum, Integer readLimit, String pathFile) {
        for (Integer count = 0 ; count < threadNum ; count ++) {
            Integer finalReadLimit = readLimit;
            Integer finalCount = count * finalReadLimit;
            commonUtil.obtainThread(()->{
                List<RecordDefault> recordDefaults = downloadMapper.excelCheckInfos(type, finalCount, finalReadLimit, pathFile);
                if (recordDefaults==null || recordDefaults.size()==0) return;
                recordDefaults.forEach((value)->{
                    DownloadExcelWriteBo downloadExcelWriteBo = copyProperties(value);
                    targetExcel.add(downloadExcelWriteBo);
                });
            });
        }
    }
}
